#include <QtTest>
#include "../tests_common.h"

#include "common.h"
#include "row_text.h"
#include "rows.h"
#include "columns.h"

using namespace BitWin;

// Define raw pointer to BitWin::Row
namespace Local
{
    typedef Row* PRow;
}

Q_DECLARE_METATYPE(Local::PRow);

// HACK! Exact type match is needed by meta-object system
#define P_ROW(p) (static_cast<Local::PRow>(p))

class TestBitsColumn: public QObject
{

    Q_OBJECT

private slots:

    void testMisc_data();
    void testMisc();

    void testData_data();
    void testData();

};

void TestBitsColumn::testMisc_data()
{
    QTest::addColumn<QString>("title");
    QTest::addColumn<BitRange>("column_range");
    
    QTest::newRow("Case 1")
        << QString("Column 1") << BitRange(0, 8)
    ;
    
    QTest::newRow("Case 2")
        << QString("Column No. 2") << BitRange(1, 8)
    ;
    
    QTest::newRow("Case 3")
        << QString("Column #3") << BitRange()
    ;
    
    QTest::newRow("Case 4")
        << QString("Column-4") << BitRange(3, 0)
    ;
}

void TestBitsColumn::testMisc()
{
    QFETCH(QString, title);
    QFETCH(BitRange, column_range);
    
    BitsColumn column(title, column_range);
    QCOMPARE(column.title(), title);
}

void TestBitsColumn::testData_data()
{
    QTest::addColumn<BitRange>("column_range");
    QTest::addColumn<Local::PRow>("p_row"); // HACK! Memory leakage is plausible
    QTest::addColumn<QString>("indata");
    QTest::addColumn<PRowText>("outdata_expected");
    
    QTest::newRow("Column: [0, 8), whole word")
        << BitRange(0, 8)
        << P_ROW(new WordRow("Row", 0))
        << QString("abcdefgh") << STRING_TEXT("abcdefgh")
    ;
    
    QTest::newRow("Column: [1, 8), whole word")
        << BitRange(1, 8)
        << P_ROW(new WordRow("Row", 0))
        << QString("abcdefgh") << STRING_TEXT("bcdefgh")
    ;
    
    QTest::newRow("Column: [3, 6), whole word")
        << BitRange(3, 6)
        << P_ROW(new WordRow("Row", 0))
        << QString("abcdefgh") << STRING_TEXT("def")
    ;
    
    QTest::newRow("Column: [0, 8), Field: [3, 6)")
        << BitRange(0, 8)
        << P_ROW(new FieldRow("Row", BitRange(3, 6), 0))
        << QString("abcdefgh") << STRING_TEXT("   def  ")
    ;
    
    QTest::newRow("Column: [3, 8), Field: [3, 6)")
        << BitRange(3, 8)
        << P_ROW(new FieldRow("Row", BitRange(3, 6), 0))
        << QString("abcdefgh") << STRING_TEXT("def  ")
    ;
    
    QTest::newRow("Column: [3, 6), Field: [0, 8)")
        << BitRange(3, 6)
        << P_ROW(new FieldRow("Row", BitRange(0, 8), 0))
        << QString("abcdefgh") << STRING_TEXT("def")
    ;
    
    QTest::newRow("Column: [2, 6), Field: [4, 7)")
        << BitRange(2, 6)
        << P_ROW(new FieldRow("Row", BitRange(4, 7), 0))
        << QString("abcdefgh") << STRING_TEXT("  ef")
    ;
    
    QTest::newRow("Column: [4, 7), Field: [2, 6)")
        << BitRange(4, 7)
        << P_ROW(new FieldRow("Row", BitRange(2, 6), 0))
        << QString("abcdefgh") << STRING_TEXT("ef ")
    ;
}

void TestBitsColumn::testData()
{
    QString title("Column");
    QFETCH(BitRange, column_range);
    BitsColumn column(title, column_range);
    
    QFETCH(Local::PRow, p_row);
    QFETCH(QString, indata);
    
    QVERIFY(!column.data(Qt::DisplayRole, p_row, STRING_TEXT(indata)).isValid());
    QVERIFY(!column.data(BitwiseDataRole + 1, p_row, STRING_TEXT(indata)).isValid());
    
    QVariant data(column.data(BitwiseDataRole, p_row, STRING_TEXT(indata)));
    QVERIFY(data.isValid());
    QVERIFY(data.canConvert<PRowText>());
    
    PRowText outdata(data.value<PRowText>());
    QFETCH(PRowText, outdata_expected);
    QCOMPARE(outdata, outdata_expected);
}

QTEST_MAIN(TestBitsColumn)

#include "main.moc"
